package com.longqin.business.service.impl;

import com.longqin.business.entity.BusProject;
import com.longqin.business.entity.BusProjectMember;
import com.longqin.business.entity.BusProjectMilestone;
import com.longqin.business.entity.BusProjectPlan;
import com.longqin.business.entity.BusProjectProblem;
import com.longqin.business.entity.BusProjectRequirement;
import com.longqin.business.entity.BusRequirement;
import com.longqin.business.mapper.BusProjectMapper;
import com.longqin.business.mapper.BusProjectMemberMapper;
import com.longqin.business.mapper.BusProjectMilestoneMapper;
import com.longqin.business.mapper.BusProjectPlanMapper;
import com.longqin.business.mapper.BusProjectProblemMapper;
import com.longqin.business.mapper.BusProjectRequirementMapper;
import com.longqin.business.service.IBusProjectService;
import com.longqin.business.util.OperationLog;
import com.longqin.business.util.RedisUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 项目管理 服务实现类
 * </p>
 *
 * @author longqin
 * @since 2025-01-21
 */
@Service
public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProject> implements IBusProjectService {

	@Autowired
	BusProjectMapper busProjectMapper;
	
	@Autowired
	BusProjectMilestoneMapper busProjectMilestoneMapper;
	
	@Autowired
	BusProjectMemberMapper busProjectMemberMapper;
	
	@Autowired
	BusProjectRequirementMapper busProjectRequirmentMapper;
	
	@Autowired
	BusProjectPlanMapper busProjectPlanMapper;
	
	@Autowired
	BusProjectProblemMapper busProjectProblemMapper;
	
	@Autowired
	RedisUtil redisUtil;
	
	private static final String CODE_PREFIX = "XMSQ"; // 项目编码前缀
	private static final String CODE_REDIS_KEY = "project_code"; // 自增项目编码REDIS存储KEY
	
	@Override
    public BusProject getById(int id) {
		BusProject project = busProjectMapper.selectById(id);
		List<BusProjectMilestone> milestones = busProjectMilestoneMapper.selectByProjectId(id);
		if (milestones != null){
			project.setMilestones(milestones.toArray(new BusProjectMilestone[0]));
		}
		List<BusProjectMember> members = busProjectMemberMapper.selectByProjectId(id);
		if (members != null){
			project.setMembers(members.toArray(new BusProjectMember[0]));
		}
		List<BusRequirement> requirements = busProjectRequirmentMapper.selectByProjectId(id);
		if (requirements != null){
			project.setRequirementList(requirements.toArray(new BusRequirement[0]));
			requirements.stream().map(s -> s.getId()).collect(Collectors.toList());
			project.setRequirements(requirements.stream().map(s -> s.getId()).collect(Collectors.toList()).toArray(new Integer[0]));
		}
		return project;
    }
	
	@Override
    public List<BusProject> getPage(String projectName, int organizationId, int userId, int startIndex, int pageSize) {
		List<BusProject> projects = busProjectMapper.selectPage(projectName, organizationId, userId, startIndex, pageSize);
		String currentDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
		if (null != projects){
			projects.forEach(s -> {
				BusProjectMilestone currentMilestone = busProjectMilestoneMapper.selectCurrentMilestone(s.getId(), currentDate);
				if (null != currentMilestone){
					s.setMilestoneName(currentMilestone.getMilestoneName());
					s.setMilestoneDate(currentMilestone.getMilestoneDate());
				}
			});
		}
		return projects;
    }
    
	@Override
    public int getCount(String projectName, int organizationId, int userId) {
        return busProjectMapper.selectCount(projectName, organizationId, userId);
    }
	
	@OperationLog(title = "删除项目", content = "'项目id：' + #id", operationType = "1")
	@Override
    public int delete(int id) throws Exception {
		return busProjectMapper.updateStatus(0, id);
    }
	
	@Override
    public int updateStatus(int status, int id) throws Exception {
		return busProjectMapper.updateStatus(status, id);
    }
	
	@Override
    public int updateBeginDate(int id) throws Exception {
		return busProjectMapper.updateBeginDate(id);
    }
	
	@OperationLog(title = "创建项目", content = "'项目名称：' + #entity.getProjectName()", operationType = "0")
	@Override
    public int create(BusProject entity) throws Exception {
		entity.setProjectCode(generateCode(CODE_REDIS_KEY));
		int result = busProjectMapper.insert(entity);
		if (result > 0){
			int groupSeq = 1; // 计划排序
			for(BusProjectMilestone milestone : entity.getMilestones()){
				milestone.setProjectId(entity.getId());
				busProjectMilestoneMapper.insert(milestone);
				// 插入里程碑计划
				BusProjectPlan milestonePlan = new BusProjectPlan();
				milestonePlan.setTaskName(milestone.getMilestoneName());
				milestonePlan.setProjectId(entity.getId());
				milestonePlan.setGroupSeq(groupSeq);
				busProjectPlanMapper.insert(milestonePlan);
				// 插入里程碑任务计划
				BusProjectPlan taskPlan = new BusProjectPlan();
				taskPlan.setTaskName(milestone.getMilestoneTask());
				taskPlan.setProjectId(entity.getId());
				taskPlan.setParentId(milestonePlan.getId());
				taskPlan.setGroupSeq(1);
				busProjectPlanMapper.insert(taskPlan);
				groupSeq++;
			}
			for(BusProjectMember member : entity.getMembers()){
				for(Integer userId : member.getUserIdArr()){
					BusProjectMember newMember = new BusProjectMember();
					newMember.setMemberType(member.getMemberType());
					newMember.setUserId(userId);
					newMember.setProjectId(entity.getId());
					busProjectMemberMapper.insert(newMember);
				}
			}
			if (null != entity.getRequirements()){
				for(Integer requirmentId : entity.getRequirements()){
					BusProjectRequirement requirement = new BusProjectRequirement();
					requirement.setRequirementId(requirmentId);
					requirement.setProjectId(entity.getId());
					busProjectRequirmentMapper.insert(requirement);
				}
			}
		}
		return result;
	}
	
	@OperationLog(title = "修改项目", content = "'项目名称：' + #entity.getProjectName()", operationType = "2")
	@Override
    public int update(BusProject entity) throws Exception {
		int result = busProjectMapper.updateById(entity);
		if (result > 0){
			busProjectMilestoneMapper.deleteByProjectId(entity.getId());
			busProjectPlanMapper.deleteByProjectId(entity.getId());
			int groupSeq = 1; // 计划排序
			for(BusProjectMilestone milestone : entity.getMilestones()){
				milestone.setProjectId(entity.getId());
				busProjectMilestoneMapper.insert(milestone);
				// 插入里程碑计划
				BusProjectPlan milestonePlan = new BusProjectPlan();
				milestonePlan.setTaskName(milestone.getMilestoneName());
				milestonePlan.setProjectId(entity.getId());
				milestonePlan.setGroupSeq(groupSeq);
				busProjectPlanMapper.insert(milestonePlan);
				// 插入里程碑任务计划
				BusProjectPlan taskPlan = new BusProjectPlan();
				taskPlan.setTaskName(milestone.getMilestoneTask());
				taskPlan.setProjectId(entity.getId());
				taskPlan.setParentId(milestonePlan.getId());
				taskPlan.setGroupSeq(1);
				busProjectPlanMapper.insert(taskPlan);
				groupSeq++;
			}
			busProjectMemberMapper.deleteByProjectId(entity.getId());
			for(BusProjectMember member : entity.getMembers()){
				for(Integer userId : member.getUserIdArr()){
					BusProjectMember newMember = new BusProjectMember();
					newMember.setMemberType(member.getMemberType());
					newMember.setUserId(userId);
					newMember.setProjectId(entity.getId());
					busProjectMemberMapper.insert(newMember);
				}
			}
			busProjectRequirmentMapper.deleteByProjectId(entity.getId());
			if (null != entity.getRequirements()){
				for(Integer requirmentId : entity.getRequirements()){
					BusProjectRequirement requirement = new BusProjectRequirement();
					requirement.setRequirementId(requirmentId);
					requirement.setProjectId(entity.getId());
					busProjectRequirmentMapper.insert(requirement);
				}
			}
		}
		return result;
	}
	
	// 生成项目编码
	private String generateCode(String key){
		String requestId = UUID.randomUUID().toString();
		int seq = 1;
		boolean isReleaseLock = true; // 是否释放锁
		String lockKey = key + "_lock";
		try {
			boolean mLock = redisUtil.lock(requestId, lockKey, 1 * 10);//锁的有效时间10秒
			if(mLock){
				isReleaseLock = false;
				seq = (int) redisUtil.incrKey(key, 1, getNowToNextDayMilliseconds(), TimeUnit.SECONDS);
				redisUtil.releaseLock(requestId, lockKey);//释放锁
				isReleaseLock = true;
			}
		} catch (Exception e) {

		}finally{
			if(!isReleaseLock){
				redisUtil.releaseLock(requestId, lockKey);
			}
		}
		LocalDate now = LocalDate.now();
		String code = CODE_PREFIX + now.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + seq;
		return code;
	}
	
	// 今日剩余时间计算
    private Long getNowToNextDayMilliseconds() {
        //获取当前时间
        Calendar calendar = Calendar.getInstance();
        //当前天+1
        calendar.add(Calendar.DAY_OF_YEAR, 1);
        //将时分秒毫秒都设为0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        //减去当前时间获取插值
        return (calendar.getTimeInMillis() - System.currentTimeMillis());
    }
    
    @Override
    public BusProject getByWorkId(int workId) {
    	BusProject project = busProjectMapper.selectByWorkId(workId);
    	if (project == null) return null;
    	List<BusProjectMilestone> milestones = busProjectMilestoneMapper.selectByProjectId(project.getId());
		if (milestones != null){
			project.setMilestones(milestones.toArray(new BusProjectMilestone[0]));
		}
		List<BusProjectMember> members = busProjectMemberMapper.selectByProjectId(project.getId());
		if (members != null){
			project.setMembers(members.toArray(new BusProjectMember[0]));
		}
		List<BusRequirement> requirements = busProjectRequirmentMapper.selectByProjectId(project.getId());
		if (requirements != null){
			project.setRequirementList(requirements.toArray(new BusRequirement[0]));
			requirements.stream().map(s -> s.getId()).collect(Collectors.toList());
			project.setRequirements(requirements.stream().map(s -> s.getId()).collect(Collectors.toList()).toArray(new Integer[0]));
		}
		return project;
    }
    
    @Override
	public List<Map<String, Object>> getPlanTree(Integer projectId) {
		List<BusProjectPlan> plans = busProjectPlanMapper.selectByProjectId(projectId);
		return createTree(plans);
	}

	@SuppressWarnings("unchecked")
	private List<Map<String, Object>> createTree(List<BusProjectPlan> plans) {
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		Map<Integer, Map<String, Object>> map = new LinkedHashMap<Integer, Map<String, Object>>();
		for (int i = 0; i < plans.size(); i++) {
			Map<String, Object> cmap = new HashMap<String, Object>();
			BusProjectPlan item = plans.get(i);
			cmap = setMap(cmap, item);
			cmap.put("state", "open");// 默认打开
			map.put(item.getId(), cmap);
		}
		// 节点级联关系
		for (Map.Entry<Integer, Map<String, Object>> entry : map.entrySet()) {
			if (map.containsKey(entry.getValue().get("parentId"))) {
				Map<String, Object> parent = map.get(entry.getValue().get("parentId"));
				Object children = parent.get("children");
				if (children == null){
					parent.put("children", new ArrayList<Map<String, Object>>());
				}
				((List<Map<String, Object>>) parent.get("children")).add(entry.getValue());
			} else {
				result.add(entry.getValue());
			}
		}
		return result;
	}

	private Map<String, Object> setMap(Map<String, Object> map, BusProjectPlan plan) {
		map.put("id", plan.getId()); // id
		map.put("parentId", plan.getParentId());// 上级id
		map.put("taskName", plan.getTaskName());// 任务名称
		map.put("userId", plan.getUserId());// 责任人id
		map.put("nickName", plan.getNickName());// 责任人昵称
		map.put("beginDate", plan.getBeginDate());// 计划开始时间
		map.put("endDate", plan.getEndDate());// 计划完成时间
		map.put("groupSeq", plan.getGroupSeq());// 任务排序
		map.put("status", plan.getStatus());// 任务状态
		map.put("attachments", plan.getAttachments());// 任务排序
		map.put("remark", plan.getRemark());// 任务备注
		map.put("realEndDate", plan.getRealEndDate());// 任务实际完成时间
		map.put("completionRate", plan.getCompletionRate());// 任务完成率
		map.put("delayReason", plan.getDelayReason());// 任务延期原因
		return map;
	}
	
	@OperationLog(title = "保存项目计划", content = "'项目id：' + #projectId", operationType = "0")
	@Override
    public void saveProjectPlan(Integer projectId, List<BusProjectPlan> plans) throws Exception {
		List<Integer> planIds = new ArrayList<>();
		plans.forEach((plan) -> {
			if (plan.getId() != null){
				busProjectPlanMapper.updateById(plan);
				planIds.add(plan.getId());
			}
			else{
				plan.setProjectId(projectId);
				busProjectPlanMapper.insert(plan);
				planIds.add(plan.getId());
			}
			if (plan.getChildren() != null){
				for (int i = 0; i < plan.getChildren().size(); i++){
					BusProjectPlan child = plan.getChildren().get(i);
					child.setGroupSeq(i + 1);
					if (child.getId() != null){
						busProjectPlanMapper.updateById(child);
						planIds.add(child.getId());
					}
					else{
						child.setProjectId(projectId);
						busProjectPlanMapper.insert(child);
						planIds.add(child.getId());
					}
				}
			}
		});
		// 获取原任务列表判断是否删除
		List<BusProjectPlan> sourceList = busProjectPlanMapper.selectList(new QueryWrapper<BusProjectPlan>().lambda());
		for(BusProjectPlan item : sourceList){
			if (!planIds.contains(item.getId())){
				busProjectPlanMapper.deleteById(item.getId());
			}
		}
	}
	
	@OperationLog(title = "处理项目计划", content = "'项目计划id：' + #entity.getId()", operationType = "2")
	@Override
    public int dealProjectPlan(BusProjectPlan entity) throws Exception {
		entity.setStatus(3);
		return busProjectPlanMapper.updateById(entity);
	}
	
	/***************************************************项目问题***********************************************************/
	@Override
    public List<BusProjectProblem> getProblemPage(Integer projectId, String title, String beginTime, String endTime, int startIndex, int pageSize) {
		return busProjectProblemMapper.selectPage(projectId, title, beginTime, endTime, startIndex, pageSize);
    }
    
	@Override
    public int getProblemCount(Integer projectId, String title, String beginTime, String endTime) {
        return busProjectProblemMapper.selectCount(projectId, title, beginTime, endTime);
    }
	
	@OperationLog(title = "创建问题", content = "'问题标题：' + #entity.getTitle()", operationType = "0")
	@Override
    public int createProblem(BusProjectProblem entity) throws Exception {
		return busProjectProblemMapper.insert(entity);
	}
	
	@OperationLog(title = "修改问题", content = "'问题标题：' + #entity.getTitle()", operationType = "2")
	@Override
    public int updateProblem(BusProjectProblem entity) throws Exception {
		return busProjectProblemMapper.updateById(entity);
	}
	
	@Override
    public BusProjectProblem getProblemById(int id) {
		return busProjectProblemMapper.selectById(id);
    }
	
	@Override
    public BusProjectProblem getProblemByWorkId(int workId) {
    	return busProjectProblemMapper.selectByWorkId(workId);
    }
	
	@Override
    public int updateProblemStatus(int status, int id) throws Exception {
		return busProjectProblemMapper.updateStatus(status, id);
    }
}
